﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
using SalesSys.BLL;
using SalesSys.Comm.BLL;
using SalesSys.Comm.DAL;
using SalesSys.Comm.Utility;

namespace SalesSys.BLL
{
    public class BllFactory
    {
      public  static  T GetBll<T>() where T : IBaseBLL, new()
        {
            return new T();
        }
    }

    /// <summary>
    /// 业务标记
    /// </summary>
    public interface IBaseBLL
    {

    }
    public interface IBaseBLL<T, in TID> : IBaseBLL<T> where T : class,IDbEntity<TID>
    {
           T[] GetList(int pageNum = 1, int pageSize = 10);
        int Delete(params TID[] ids);
           int Delete(TID id);
           T Details(TID id);
            int Edit(T entity);
            int Create(T entity);
        int Create(IEnumerable<T> entitys);
        int Delete(IEnumerable<T> entitys);

        KeyValuePair<int, IEnumerable<T>> GetPaging<key>(Expression<Func<T, bool>> predicate,
            Expression<Func<T, key>> keySelector, bool isDesc = false, int pageNum = 1, int pageSize = 1);


    }

    public interface IBaseBLL<T> : IBaseBLL where T : class, IDbEntity
    {
        T Details(params  object[] ids);
        int Create(T entity);
        int Create(IEnumerable<T> entitys);
        int Edit(T entity);
        int Edit(T[] entitys);
        int Delete(T entity);
        int Delete(IEnumerable<T> entitys);
        T[] GetList(Expression<Func<T, bool>> predicate, out int total, string order, bool isDesc, int pageNum = 1, int pageSize = 10);
        T[] GetList(Expression<Func<T, bool>> predicate);
    }

    public class BaseBLL<T> :  IBaseBLL<T> where T : class,IDbEntity
    {
        protected IRepository<T> _rep;

        /// <summary>
        /// 业务相关仓储
        /// </summary>
        protected virtual IRepository<T> Rep
        {
            get { return _rep ?? (_rep = RepositoryFactory.GetRepositoryByFactoryUnit<IRepository<T>>()); }
            set { _rep = value; }
        }

        public virtual T Details(params  object[] ids)
        {
          return   Rep.Find(ids);
        }

        public virtual int Create(T entity)
        {
            return Rep.Insert(entity);
        }
        public virtual int Create(IEnumerable<T> entitys)
        {

            return Rep.Insert(entitys);
        }
        public virtual int Edit(T entity)
        {
            return Rep.Update(entity);
        }
        public virtual int Edit(T[] entitys)
        {
            return Rep.Update(entitys);
        }
        public virtual int Delete(T entity)
        {
            return Rep.Delete(entity);
        }
        public virtual int Delete(IEnumerable<T> entitys)
        {
            return Rep.Delete(entitys);
        }


           protected virtual T[] GetList(IEnumerable<SqlItem> sqlWhere, KeyValuePair<string, bool>[] orderBy, int pageNum = 1, int pageSize = 10)
        {
            FastCheck.Required(pageNum > 0, "页码错误");
            FastCheck.Required(pageSize > 0, "页大小错误");
            var orderByList = orderBy.Select(p => new KeyValuePair<string, ListSortDirection>(p.Key, p.Value ? ListSortDirection.Descending : ListSortDirection.Ascending)).ToArray();
            var list = Rep.QueryByWhere(sqlWhere, pageNum, pageSize, orderByList).ToArray();
            return list;
        }
        public T[] GetList(Expression<Func<T, bool>> predicate, out int total, string order, bool isDesc, int pageNum = 1, int pageSize = 10)
        {
            // Rep.Entities.Where(predicate).OrderBy(order, isDesc ? ListSortDirection.Descending : ListSortDirection.Ascending).Paging(pageNum, pageSize);

            if (order == null)
            {
                return Rep.Entities.Query(predicate, pageNum, pageSize, out total, null).ToArray();
            }
            return Rep.Entities.Query(predicate, pageNum, pageSize, out total, new[] { order.ToSortCondition(isDesc) }).ToArray();
        }

        public T[] GetList(Expression<Func<T, bool>> predicate)
        {
            if (predicate == null)
            {
                return Rep.Entities.ToArray();
            }
            else
            {
                return Rep.Entities.Where(predicate).ToArray();
            }
        }
    }

    public class BaseBLL<T, TID> :BaseBLL<T>,  IBaseBLL<T, TID> where T : class,IDbEntity<TID>
    {

        public virtual int Delete(params TID[] ids)
        {
            return Rep.Delete(p=>ids.Contains(p.Id));
        } 
       public virtual int Delete(TID id)
       {
           return Rep.Delete(id);
       }
       public virtual T Details(TID id)
       {
           return Rep.Find(id);
       }
       public virtual IEnumerable<T> DetailsMany(params TID[] ids)
       {
           return Rep.Entities.Where(p => ids.Contains(p.Id)).ToArray();
       }
       public virtual T[] GetList(int pageNum,int pageSize=10)
       {
           FastCheck.Required(pageNum > 0, "页码错误");
           FastCheck.Required(pageSize > 0, "页大小错误");
           return Rep.Entities.OrderBy(p=>p.Id).Paging(pageNum, pageSize).ToArray();
       }

        /// <summary>
        /// 返回总数量及数据
        /// </summary>
        /// <typeparam name="key"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="keySelector"></param>
        /// <param name="isDesc"></param>
        /// <param name="pageNum"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
       public virtual KeyValuePair<int, IEnumerable<T>> GetPaging<key>(Expression<Func<T, bool>> predicate, Expression<Func<T, key>> keySelector, bool isDesc = false, int pageNum = 1, int pageSize = 1)
       {
           var list = Rep.Entities;
           if (predicate != null)
           {
               list = list.Where(predicate);
           }
         
           int total = list.Count();
           IEnumerable<T> reList = null;
           if (keySelector==null)
           {
               reList=list.OrderBy(p=>p.Id).Paging(pageNum,pageSize).ToArray();
                return new KeyValuePair<int, IEnumerable<T>>(total, reList);
           }
           
           if (isDesc)
           {
               reList = list.OrderByDescending(keySelector).Paging(pageNum, pageSize);
           }
           else
               reList = list.OrderBy(keySelector).Paging(pageNum, pageSize);
           return new KeyValuePair<int, IEnumerable<T>>(total, reList.ToArray());
       }
     
    }

}
